"""
JWT工具类：生成和验证Token
"""
import jwt
from jwt.exceptions import InvalidTokenError
from datetime import datetime, timedelta
from typing import Dict, Optional
from fastapi import HTTPException, status

# JWT配置
SECRET_KEY = "your-secret-key-change-this-in-production-2024"  # 生产环境务必修改
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30  # 访问令牌30分钟
REFRESH_TOKEN_EXPIRE_DAYS = 7  # 刷新令牌7天


def create_access_token(data: Dict, expires_delta: Optional[timedelta] = None) -> str:
    """
    创建访问令牌
    :param data: 要编码的数据（通常包含user_id、username等）
    :param expires_delta: 过期时间差
    :return: JWT Token
    """
    to_encode = data.copy()
    
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    
    to_encode.update({
        "exp": expire,
        "type": "access"
    })
    
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt


def create_refresh_token(data: Dict) -> str:
    """
    创建刷新令牌
    :param data: 要编码的数据
    :return: JWT Refresh Token
    """
    to_encode = data.copy()
    expire = datetime.utcnow() + timedelta(days=REFRESH_TOKEN_EXPIRE_DAYS)
    
    to_encode.update({
        "exp": expire,
        "type": "refresh"
    })
    
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt


def verify_token(token: str, token_type: str = "access") -> Dict:
    """
    验证Token
    :param token: JWT Token
    :param token_type: 令牌类型（access或refresh）
    :return: 解码后的数据
    :raises: HTTPException 如果Token无效
    """
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        
        # 验证token类型
        if payload.get("type") != token_type:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail=f"Invalid token type, expected {token_type}",
                headers={"WWW-Authenticate": "Bearer"},
            )
        
        return payload
    
    except jwt.ExpiredSignatureError:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Token has expired",
            headers={"WWW-Authenticate": "Bearer"},
        )
    
    except InvalidTokenError:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Could not validate credentials",
            headers={"WWW-Authenticate": "Bearer"},
        )


def decode_token(token: str) -> Optional[Dict]:
    """
    解码Token（不验证是否过期，仅用于调试）
    :param token: JWT Token
    :return: 解码后的数据，失败返回None
    """
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM], options={"verify_exp": False})
        return payload
    except InvalidTokenError:
        return None

